#pragma once
#include "stdafx.h"
#include "pass.h"
#include "Form1.h"

namespace aps {
#define NAME_LENGTH 39

/*
Functions takes path to certificate as input, length and outputs its content i
BYTE array, and puts length of certificate read in length
*/

static BYTE* readCertificate(const char* path, int *len)
{
char * mem;
int size;

        ifstream file (path, ios::in|ios::binary|ios::ate);
                if (file.is_open()) {
                        size = file.tellg();
                        mem = new char [size];
                        file.seekg (0, ios::beg);
                        file.read (mem, size);
                        file.close();
                        *len = size;
                        return (BYTE*) mem;
                } else return NULL;
}

void PassportInfo::setConnection(void) {
	System::String ^str = "dsn=Passport Data;uid=siddhu;pwd=siddhu;";
	connection = gcnew System::Data::Odbc::OdbcConnection(str);
	command = connection->CreateCommand();
}

void PassportInfo::freeConnection(void) {
	connection->Close();
}

PassportInfo::PassportInfo(void) {
	setConnection();
}

/*
Function returns the truncated name of length 39. If length of name is lesser than 39 then it is padded with '<', and if greater than 39 then simply dropped.
Argumentss: fileNo: file_number corresponding to passport to make
	    name: truncated name would be stored in name
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getTruncatedName(const char* fileNo, BYTE* name) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT truncated_name from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(39);
	nt->Initialize();
	Reader->GetBytes(0, 0, nt, 0, 39);
	for(int i=0;i<39;i++) name[i] = nt[i];
	freeConnection();
	return SUCCESS;
}

/*
Function returns 9 digit unique passport number from database.
Arguments: fileNo: file_number correspoing to passport to make
	   docNum: passport number would be stored docNum
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getDocNumber(const char* fileNo, BYTE* docNum) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	System::Console::WriteLine(s);
	query = System::String::Concat("SELECT passport_no from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(9);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, 9);
	for(int i=0; i<9;i++) docNum[i] = nt[i];
	freeConnection();
	return SUCCESS;
}

/*
Function returns nationality of the person.
Arguments: fileNo: file_number correspoing to passport to make
	   nation: nationality would be stored in nation
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getNationality(const char* fileNo, BYTE* nation) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT nationality from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) nation[i] = nt[i];
	freeConnection();
	return SUCCESS;
}

/*
Function returns date of birth in yymmdd format
Arguments: fileNo: file_number correspoing to passport to make
	   dob: date of birth would be stored dob
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getDOB(const char* fileNo, BYTE* dob) {
    setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT dob_yyyymmdd from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) dob[i] = nt[i];
	*(dob + 0) = *(dob + 2);
	*(dob + 1) = *(dob + 3);
	*(dob + 2) = *(dob + 5);
	*(dob + 3) = *(dob + 6);
	*(dob + 4) = *(dob + 8);
	*(dob + 5) = *(dob + 9);
	*(dob + 6) = '\0';
	freeConnection();
	return SUCCESS;
}

/*
Function returns sex of the individual.
Arguments: fileNo: file_number correspoing to passport to make
	   sex: sex would be stored in this variable
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getSex(const char* fileNo, BYTE* sex) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT sex from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) sex[i] = nt[i];
	freeConnection();
	return SUCCESS;
}

/*
Function returns date of expiry or valid until date.
Arguments: fileNo: file_number correspoing to passport to make
	   doe: date of expiry is stored in doe
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getDOE(const char* fileNo, BYTE* doe) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT date_expiry from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) doe[i] = nt[i];
	*(doe + 0) = *(doe + 2);
	*(doe + 1) = *(doe + 3);
	*(doe + 2) = *(doe + 5);
	*(doe + 3) = *(doe + 6);
	*(doe + 4) = *(doe + 8);
	*(doe + 5) = *(doe + 9);
	*(doe + 6) = '\0';
	freeConnection();
	return SUCCESS;
}

	
/*
Funtion returns full name of the individual.
Arguments: fileNo: file_number correspoing to passport to make
	   fullName: full name would be stored it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getFullName(const char* fileNo, BYTE* fullName) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT full_name from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) fullName[i] = nt[i];
	freeConnection();
	return len;
}

/*
Function returns number of aliases
Arguments: fileNo: file_number correspoing to passport to make
	   numOthers: number of aliases is stored in this
Returns: On success, returns number of other names in the database
	 else returns Failure
*/
int PassportInfo::getNumOtherNames(const char* fileNo, BYTE* numOthers, int* sizebuf) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT COUNT(*) from alias where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	*numOthers = Reader->GetInt32(0);
	int len = Reader->GetValue(0)->ToString()->Length;
	*sizebuf = len;
	len = Reader->GetInt32(0);
	freeConnection();
	return len;
}

/*
Function returns i'th alias name in other name and returns
Arguments: fileNo: file_number correspoing to passport to make
	   otherName: stores alias name in this
	   i: details of i'th alias is being asked for
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getOtherName(const char* fileNo, BYTE* otherName, int i) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT alias_name from alias where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	while (i >= 0) {
		Reader->Read();
		i--;
	}
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) otherName[i] = nt[i];
	freeConnection();
	return len;
}

/*
Function returns date of birth in yyyymmdd format
Arguments: fileNo: file_number correspoing to passport to make
	   fullDOB: full date of birth is stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getFullDOB(const char* fileNo, BYTE* fullDOB) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT dob_yyyymmdd from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) fullDOB[i] = nt[i];
	*(fullDOB + 4) = *(fullDOB + 5);
	*(fullDOB + 5) = *(fullDOB + 6);
	*(fullDOB + 6) = *(fullDOB + 8);
	*(fullDOB + 7) = *(fullDOB + 9);
	*(fullDOB + 8) = '\0';
	freeConnection();
	return 8;
}

/*
Function returns place of birth.
Arguments: fileNo: file_number correspoing to passport to make
	   placeBirth: place of birth would be stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getPlaceBirth(const char* fileNo, BYTE* placeBirth) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT place_of_birth from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) placeBirth[i] = nt[i];
	freeConnection();
	return len; 
}

/*
Function returns permanent address.
Arguments: fileNo: file_number correspoing to passport to make
	   addr: permanent address is stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getPermAddr(const char* fileNo, BYTE* addr) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT permanent_address from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) addr[i] = nt[i];
	freeConnection();
	return len;
}

/*
Function returns issuing authority.
Arguments: fileNo: file_number correspoing to passport to make
	   issueAuth: issuing authority is stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getIssueAuth(const char* address, BYTE* issueAuth) {
	int certLen = -1;
       	BYTE* certDO = readCertificate(address, &certLen); 

	list<DO> level1 = getList(certLen, certDO);
        DO &l1seq = level1.front();

        list<DO> level2 = getList(l1seq.getLength(), l1seq.getValue());
        DO &l2seq = level2.front();

        list<DO> level3 = getList(l2seq.getLength(),l2seq.getValue());
        level3.pop_front();
        level3.pop_front();
        level3.pop_front();
        level3.pop_front();
        level3.pop_front();
        DO &l3seq = level3.front();

        list<DO> level4 = getList(l3seq.getLength(),l3seq.getValue());
        BYTE *tmp = (BYTE*)malloc(100);
        int length = 0;
        list<DO> level6;
        list<DO> level7;
        int i = 0;
        while (!level4.empty())
        {
                DO &l5set = level4.front();
                list<DO> level6 = getList(l5set.getLength(), l5set.getValue());
                DO &l6seq = level6.front();
                list<DO> level7 = getList(l6seq.getLength(),l6seq.getValue());
                level7.pop_front();
                DO &printstr = level7.front();
                tmp = printstr.getValue();
                tmp [printstr.getLength()] = '<';
                memcpy(issueAuth + length, tmp, printstr.getLength()+1);
                length += printstr.getLength() + 1;
                level4.pop_front();
        }
        return length-1;
}

/*
Function returns date of issue
Arguments: fileNo: file_number correspoing to passport to make
	   dateIssue: date of issue is stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getDateIssue(const char* fileNo, BYTE* dateIssue) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT date_issue from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) dateIssue[i] = nt[i];
	*(dateIssue + 4) = *(dateIssue + 5);
	*(dateIssue + 5) = *(dateIssue + 6);
	*(dateIssue + 6) = *(dateIssue + 8);
	*(dateIssue + 7) = *(dateIssue + 9);
	*(dateIssue + 8) = '\0';
	freeConnection();
	return 8;
}

/*Important: take care of this field
Function stores timestamp when passport officer signs the passport
Arguments: fileNo: file_number correspoing to passport to make
	   dttimePers: the then timestamp would be stored in this
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getTimestampPers(const char* fileNo, BYTE* dttimePers) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT personalization_timestamp from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) dttimePers[i] = nt[i];
	*(dttimePers + 4) = *(dttimePers + 5);
	*(dttimePers + 5) = *(dttimePers + 6);
	*(dttimePers + 6) = *(dttimePers + 8);
	*(dttimePers + 7) = *(dttimePers + 9);
	*(dttimePers + 8) = *(dttimePers + 11);
	*(dttimePers + 9) = *(dttimePers + 12);
	*(dttimePers + 10) = *(dttimePers + 14);
	*(dttimePers + 11) = *(dttimePers + 15);
	*(dttimePers + 12) = *(dttimePers + 17);
	*(dttimePers + 13) = *(dttimePers + 18);
	*(dttimePers + 14) = '\0';
	freeConnection();
	return 14;
}

/*
Function returns place of issue of passport.
Arguments: fileNo: file_number correspoing to passport to make
	   placeIssue: place of issue is stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getPlaceIssue(const char* fileNo, BYTE* placeIssue) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT place_issue from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	Reader->Read();
	int len = Reader->GetValue(0)->ToString()->Length;
	array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
	nt->Initialize();
	Reader->Close();
	Reader = command->ExecuteReader();
	Reader->Read();
	Reader->GetBytes(0, 0, nt, 0, len);
	for(int i=0; i<len;i++) placeIssue[i] = nt[i];
	freeConnection();
	return len;
}

/*
Function returns father's name.
Arguments: fileNo: file_number correspoing to passport to make
	   fname: father's name would be stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getFathersName(const char* fileNo, BYTE* fname) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT father_name from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	int len;
	if(Reader->Read()) {
		len = Reader->GetValue(0)->ToString()->Length;
		if(len==0) {
			freeConnection();
			return FAILURE;
		}
		array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
		nt->Initialize();
		Reader->Close();
		Reader = command->ExecuteReader();
		Reader->Read();
		Reader->GetBytes(0, 0, nt, 0, len);
		for(int i=0; i<len;i++) fname[i] = nt[i];
		return len;
	}
	else {
		freeConnection();
		return FAILURE;
	}
}

/*
Function returns mother's name.
Arguments: fileNo: file_number correspoing to passport to make
	   mname: mother's name would be stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getMothersName(const char* fileNo, BYTE* mname) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT mother_name from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	int len;
	if(Reader->Read()) {
		len = Reader->GetValue(0)->ToString()->Length;
		if(len==0) {
			freeConnection();
			return FAILURE;
		}
		array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
		nt->Initialize();
		Reader->Close();
		Reader = command->ExecuteReader();
		Reader->Read();
		Reader->GetBytes(0, 0, nt, 0, len);
		for(int i=0; i<len;i++) mname[i] = nt[i];
		return len;
	}
	else {
		freeConnection();
		return FAILURE;
	}
}
	
/*
Function returns spouse name.
Arguments: fileNo: file_number correspoing to passport to make
	   mname: spouse name would be stored in it
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getSpouseName(const char* fileNo, BYTE* sname) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT spouse_name from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	int len;
	if(Reader->Read()) {
		len = Reader->GetValue(0)->ToString()->Length;
		if(len==0) {
			freeConnection();
			return FAILURE;
		}
		array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
		nt->Initialize();
		Reader->Close();
		Reader = command->ExecuteReader();
		Reader->Read();
		Reader->GetBytes(0, 0, nt, 0, len);
		for(int i=0; i<len;i++) sname[i] = nt[i];
		return len;
	}
	else {
		freeConnection();
		return FAILURE;
	}
}

/*
Function returns old passport number(if any)
Arguments: fileNo: file_number correspoing to passport to make
	   oldFileNo: passport number would be stored docNum
Returns: Success or failure depending on retrieval from database
*/
int PassportInfo::getOldPassportNum(char* fileNo, char* oldFileNo) {
	setConnection();
	System::String ^s = gcnew System::String(fileNo);
	query = System::String::Concat("SELECT old_passport_no from pdata where file_number = '", s, "'");
	command->CommandText = query;
	connection->Open();
	Reader = command->ExecuteReader();
	int len;
	if(Reader->Read()) {
		len = Reader->GetValue(0)->ToString()->Length;
		if(len==0) {
			freeConnection();
			return FAILURE;
		}
		array<System::Byte, 1> ^nt = gcnew array<System::Byte, 1>(len);
		nt->Initialize();
		Reader->Close();
		Reader = command->ExecuteReader();
		Reader->Read();
		Reader->GetBytes(0, 0, nt, 0, len);
		for(int i=0;i<len;i++) oldFileNo[i] = nt[i];
		Reader->Close();
	}
	else {
		freeConnection();
		return FAILURE;
	}
	oldFileNo[len] = '\0';
	freeConnection();
	return SUCCESS;
}
}